/*
 * Copyright (C) 2011 Cyril Mottier (http://www.cyrilmottier.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package greendroid.image;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.widget.ImageView.ScaleType;

/**
 * Scales Bitmaps according to a given width and height. The scaling method may
 * be one of the ScaleType values
 * 
 * @author Cyril Mottier
 * @author kennydude
 */
public class ScaleImageProcessor implements ImageProcessor {

	private int mWidth;
	private int mHeight;
	private ScaleType mScaleType;
	private final Matrix mMatrix = new Matrix();

	private final RectF mTempSrc = new RectF();
	private final RectF mTempDst = new RectF();

	/**
	 * Create a new ScaleImageProcessor.
	 * 
	 * @param width
	 *            The width of the final surrounding box
	 * @param height
	 *            The height of the final surrounding box
	 * @param scaleType
	 *            The ScaleType method used to scale the original Bitmap
	 */
	public ScaleImageProcessor(int width, int height, ScaleType scaleType) {
		mWidth = width;
		mHeight = height;
		mScaleType = scaleType;
	}

	public Bitmap processImage(Bitmap bitmap) {

		if (bitmap == null) {
			return null;
		}

		mMatrix.reset();

		final int bWidth = bitmap.getWidth();
		final int bHeight = bitmap.getHeight();

		switch (mScaleType) {

		case CENTER_CROP: {
			// Center and scale the bitmap so that it entirely fills the
			// given space. The bitmap ratio remains unchanged
			float scale;
			float dx = 0, dy = 0;

			if (bWidth * mHeight > mWidth * bHeight) {
				scale = (float) mHeight / (float) bHeight;
				dx = (mWidth - bWidth * scale) * 0.5f;
			} else {
				scale = (float) mWidth / (float) bWidth;
				dy = (mHeight - bHeight * scale) * 0.5f;
			}

			mMatrix.setScale(scale, scale);
			mMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
			break;
		}

		case CENTER: {
			// Center bitmap without scaling
			final int dx = (int) ((mWidth - bWidth) * 0.5f + 0.5f);
			final int dy = (int) ((mHeight - bHeight) * 0.5f + 0.5f);
			mMatrix.setTranslate(dx, dy);
			break;
		}

		case CENTER_INSIDE: {
			// Center and scale the bitmap so that it entirely fits into the
			// given space.
			float scale;
			float dx;
			float dy;

			if (bWidth <= mWidth && bHeight <= mHeight) {
				scale = 1.0f;
			} else {
				scale = Math.min((float) mWidth / (float) bWidth, (float) mHeight / (float) bHeight);
			}

			dx = (int) ((mWidth - bWidth * scale) * 0.5f + 0.5f);
			dy = (int) ((mHeight - bHeight * scale) * 0.5f + 0.5f);

			mMatrix.setScale(scale, scale);
			mMatrix.postTranslate(dx, dy);
			break;
		}

		case FIT_XY:
		default:
			// Entirely fills the space without respecting bitmap's ratio.
			mTempSrc.set(0, 0, bWidth, bHeight);
			mTempDst.set(0, 0, mWidth, mHeight);

			mMatrix.setRectToRect(mTempSrc, mTempDst, Matrix.ScaleToFit.FILL);
			break;
		}

		Bitmap result = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
		Canvas canvas = new Canvas(result);
		canvas.drawBitmap(bitmap, mMatrix, null);

		return result;
	}
}
